package com.lc.adapter;

import com.lc.config.Configuration;
import com.lc.handler.ProtocolUtil;
import com.lc.mapper.Context;
import com.lc.mapper.Host;
import com.lc.mapper.Servlet;
import com.lc.mapper.Wrapper;
import com.lc.mode.Request;
import com.lc.mode.Response;
import com.lc.utils.StaticResourceUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Map;
import java.util.stream.Stream;

/**
 * @author liuc
 * @date 2021/5/7
 * @description
 **/
public class HttpAdapter {

    private String hostName;
    private Configuration configuration;
    private Host host;

    public Host getHost() {
        return host;
    }

    public void setHost(Host host) {
        this.host = host;
    }

    public HttpAdapter(Configuration configuration, String host){
        this.configuration = configuration;
        this.hostName = host;
    }

    public void adapt(Request request, Response response){
        //匹配host,调用其方法
        try {
            //没有host表示404
            if(host == null){
                response.notFound();
                return;
            }
            //拆分path
            String[] pathArr = request.getPath().split("/");
            String contextName = null;
            int index = 0;
            //找到contextName
            for (int i = 0; i < pathArr.length; i++) {
                String s = pathArr[i];
                if(s.trim().length() == 0){
                    continue;
                }else{
                    index = i;
                    contextName = "/"+s;
                    break;
                }
            }
            Map<String, Context> contextMap = host.getContextMap();
            if(contextName == null){
                //contextName没有找到就给一个默认值
                contextName = "/";
            }
            Context context = contextMap.get(contextName);
            if(context == null){
                //前面contextName不为空但是没有找到,给一个默认的
                context = contextMap.get("/");
            }
            if(context == null){
                response.notFound();
                return;
            }
            //判断是否是静态文件
            if(isStaticFile(request.getPath())){
                String fileName = context.getDir() + "/" + getStaticFileName(request.getPath());
                if(!StaticResourceUtil.exists(fileName)){
                    response.notFound();
                    return;
                }
                writeStaticFile(fileName,response);
                return;
            }
            Wrapper wrapper = null;
            Wrapper defaultWrapper = context.getDefaultWrapper();
            if(index == pathArr.length - 1 || pathArr.length == 0){
                //index找到的是最后一个了,说明url只包含了context,没有path了
                //这个时候找第一个wrapper来处理
                wrapper = defaultWrapper;
            }else{
                wrapper = context.getWrapperMap().get(pathArr[index+1]);
            }
            if(wrapper == null){
                //wrapper没有找到则给一个默认的试试看能不能处理该请求
                wrapper = defaultWrapper;
            }
            if(wrapper == null){
                response.notFound();
                return;
            }
            doService(request,response,wrapper);
            //response.write("hello life!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 真正的执行servlet的方法
     * @param request 请求体
     * @param response 响应
     * @param wrapper servlet包装类
     * @throws IOException 异常
     */
    public void doService(Request request, Response response, Wrapper wrapper) throws IOException {
        Servlet servlet = wrapper.getServlet();
        if(servlet == null){
            response.notFound();
            return;
        }
        //调用servlet
        servlet.service(request,response);
    }

    private final String[] staticFileSuffix = {".html",".htm",".js",".css"};

    public boolean isStaticFile(String path){
        return Stream.of(staticFileSuffix).anyMatch(s -> path.endsWith(s));
    }

    public String getStaticFileName(String path){
        String[] ps = path.split("/");
        return ps[ps.length - 1];
    }

    private void writeStaticFile(String fileName, Response response) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(fileName);
        int count = 0;
        while(count == 0) {
            count = fileInputStream.available();
        }
        int resourceSize = count;
        //1.先写头部信息
        response.write(ProtocolUtil.getHttpHeader200(resourceSize).getBytes());
        //2.写具体的内容
        // 读取内容输出 已经读取的内容长度
        long written = 0 ;
        // 计划每次缓冲的长度
        int byteSize = 1024;
        byte[] bytes = new byte[byteSize];
        while(written < resourceSize) {
            // 说明剩余未读取大小不足一个1024长度，那就按真实长度处理
            if(written  + byteSize > resourceSize) {
                // 剩余的文件内容长度
                byteSize = (int) (resourceSize - written);
                bytes = new byte[byteSize];
            }
            fileInputStream.read(bytes);
            response.write(bytes);
            written+=byteSize;
        }
    }
}
